#!/usr/bin/env python

#FUNCIONES DEL MODULO:
# - verificaActualiza(matrizPago, total)
#   Procesa los valores de la grilla de pagos "Formas de pago": verifica que los codigos sean correctos, determina
#   totales y subtotales; y actualiza los valores que luego seran mostrados en otro modulo
# - guardarValoresRecibidos(matrizPago,nrofactura,sucursal,idcliente)
#   Toma los valores de la grilla de pagos "Formas de pago" y los almacena en las tablas correspondientes segun
#   el tipo de pago (efectivo, cheque, tarjetas en "ventastienepagos" y cuentas corrientes y tarjeta Sussan en
#   "vtas_ctasctes"). Ademas determina las fechas de vencimientos de las cuotas.
# - generarRecibo(matrizPago,nrofactura,sucursal,fecha,idcliente)
#   Genera un numero de recibo e invoca al modulo que lo imprime pasando los datos necesarios

import consultasBD
import datetime
import time
import Imprimir
import fiscal
import utiles
import DescripcionPagos
from decimal import Decimal, getcontext, ROUND_UP
import sincronizar_tabla
import sussanException

tipodoc = {'CUIT':'C', 'CUIL':'L', 'LE':'0', 'LC':'1', 'DNI':'2', 'Pasaporte':'3', 'CI':'4' }
responsabilidad = { 'Inscripto':'I', 'Cons. Final':'C', 'Cons. Fiscal':'C', 'Monotributo':'M' }

def agregarPagoPuntos(grillaPago, total):  
    for fil in xrange(grillaPago.GetNumberRows()):
        #encontrar la primer fila vacia
        if grillaPago.GetCellValue(fil, 0) == "":
            grillaPago.SetCellValue(fil, 0, 'CL')
            grillaPago.SetCellValue(fil, 4, str(total))
            return
        
    raise sussanException.SussanException("No se encontro ninguna fila libre en la grilla de pagos")

def getTotalEnPago(grillaPago):
    ret = 0
    for fil in xrange(grillaPago.GetNumberRows()):
        if grillaPago.GetCellValue(fil, 0):
            ret += float(grillaPago.GetCellValue(fil, 4))
    return ret
            
def verificaActualiza(grillaPago, total, tipoVenta, tipoOperacion = 3, nrocliente = ""):

    if nrocliente == "":
        msg_error = 'Debe indicar el codigo de cliente'
        cod_error = 1
        error = msg_error, cod_error
        return Decimal("0.00"),error

    #columnas matrizPagos
    #0 - forma de pago
    #1 - descripcion
    #2 - cantidad de cuotas
    #3 - monto de la cuota
    #4 - total renglon
    
    #tipoOperacion
    #1 - pago de facturas
    #2 - pago de cuentas corrientes
    #3 - pago de compras ?
    
    #tipoVenta
    #1 - venta tipo 1
    #2 - venta tipo 2

    #getcontext().prec = 3 #precision : numero de decimales
    #getcontext().rounding = ROUND_UP #factor de redondeo : ROUND_UP -> hacia arriba
    decimales = Decimal('0.01')

    #transformo la grilla en una lista de listas -> matriz; esto facilitara su manipulacion
    matrizPago = [["","","","",""],["","","","",""],["","","","",""],["","","","",""]]
    cantidadRenglones = grillaPago.GetNumberRows()
    for fil in xrange(cantidadRenglones):
        if grillaPago.GetCellValue(fil,4) !="":
            if not utiles.isDecimal(grillaPago.GetCellValue(fil,4)):
                msg_error = 'Debe introducir un valor numerico'
                cod_error = 1
                error = msg_error, cod_error
                return Decimal("0.00"),error
            if Decimal(grillaPago.GetCellValue(fil,4)) < 0:
                msg_error = 'Debe introducir un valor positivo'
                cod_error = 1
                error = msg_error, cod_error
                return Decimal("0.00"),error
        for col in xrange(5):
            matrizPago[fil][col] = grillaPago.GetCellValue(fil,col)

    error = None

    for fila in xrange(cantidadRenglones):

        if matrizPago[fila][0] != "": 
            #hay un codigo de Forma de Pago introducido, entonces se procesa el renglon

            #determina monto del renglon
            if matrizPago[fila][4] != "":
                aPagar = Decimal(matrizPago[fila][4])
            else:
                #si no hay un total en el renglon, entonces se debe ver cuanto suman los otros renglones
                #y al total de la factura se le resta el total de los otros renglones. Este resto sera el
                #total de este renglon
                subtotal = Decimal("0.00")
                for x in xrange(cantidadRenglones):
                    if (matrizPago[x][4] != ""):
                        #se omite en este subtotal al renglon que se esta procesando
                        if (x != fila): subtotal = subtotal + Decimal(matrizPago[x][4])
                aPagar = Decimal(total) - subtotal
            #aPagar contiene el total del renglon, tanto si el usuario lo ha introducido como si no

            if aPagar > 0:
                #busqueda en la BD y verificacion de existencia del codigo de Forma de Pago
                tabla       = "valores"
                condicion   = "nombre = '"+matrizPago[fila][0]+"' AND tipoVenta<>'3' "
                consultaSQL = "SELECT * FROM "+tabla+" WHERE "+condicion
                resultado = consultasBD.ordenCrudaDict(consultaSQL)
                if resultado != None:
                    if len(resultado) > 0:
                        resultado = resultado[0]
                        if nrocliente == '1-2' and resultado["tipo"]==1:
                            msg_error = 'Para el cliente 1-2 no se admite pago en Cuotas'
                            cod_error = 1
                            error = msg_error, cod_error
                            return Decimal("0.00"),error
                        #como existe el codigo de Forma de Pago, se lo busca en
                        #la BD y se procede a calcular los valores de la linea
                        if (tipoOperacion != 1 ) and resultado['tipo'] != 0:
                            #esto se hace porque en caso de cuentas corrientes o tarjeta sussan, no se puede 
                            #pagar algo con tarjeta sussan o cuenta corriente. Los pagos en la cuenta corriente 
                            #deben hacerse en efectivo, cheque o tarjeta de credito
                            msg_error = 'Pagos a CUOTAS hacerse con\n Efectivo o Tarjeta de Credito'
                            cod_error = 1
                            error = msg_error, cod_error
                            for x in xrange(5): #se borra el contenido de la fila
                                matrizPago[fila][x] = ""
                        elif (tipoVenta == 2 ) and resultado['tipoVenta'] != 0:
                            #esto se hace porque las ventas tipo 2 solo pueden pagarse si el tipoVenta de la tabla valores es 0
                            msg_error = 'ATENCION: Pagos de Ventas Tipo 2\nen efectivo o en cuenta corriente.\nNo se aceptan tarjetas.'
                            cod_error = 1
                            error = msg_error, cod_error
                            for x in xrange(5): #se borra el contenido de la fila
                                matrizPago[fila][x] = ""
                        else:
                            matrizPago[fila][0] = resultado['nombre'] #codigo de forma de pago
                            matrizPago[fila][1] = resultado['descripcion'] #descripcion
                            matrizPago[fila][2] = str(resultado['valor']) #cantidad de cuotas
                            
                            if resultado['tipo'] != 0:
                                montoCuota = (Decimal(aPagar) / Decimal(matrizPago[fila][2])).quantize(Decimal('0.10'), rounding=ROUND_UP)
                                if resultado['tipo'] == 1:
                                    recargo = (montoCuota * Decimal("10")/Decimal("100.00")).quantize(Decimal("0.10"))
                                    aPagar = (aPagar * Decimal("1.10")).quantize(Decimal("0.10"))
                                else:
                                    recargo = Decimal("0.00")
                                montoCuota+= recargo
                            else:
                                montoCuota = ""
                            
                            matrizPago[fila][3] = str(montoCuota)
                            matrizPago[fila][4] = str(aPagar)
                    else:
                        msg_error = 'Codigo de "Forma de Pago" no encontrado'
                        cod_error = 1
                        error = msg_error, cod_error
                        for x in xrange(5): #se borra el contenido de la fila
                            matrizPago[fila][x] = ""
                else:
                    msg_error = 'No pudo establecerse comunicacion\ncon la base de datos'
                    cod_error = 1
                    error = msg_error, cod_error
            else: #el resto es 0 o menor a cero
                if tipoOperacion != 2:
                    msg_error = 'El total pagado se ha cumplimentado\nNo puede pagarse en exceso'
                    cod_error = 2
                    error = msg_error, cod_error
                    for x in xrange(5): #se borra el contenido de la fila
                        matrizPago[fila][x] = ""
                else:
                    utiles.mensaje(None,"Ya ha cumplimentado el importe a pagar\nSi entrega mas valores que los adeudados,\nse imputaran al pago de la cta. cte.")

        else: #no hay codigo de Forma de Pago introducido, entonces se borra el
              #renglon en caso de que haya algo de algun procesamiento anterior
            for x in xrange(5): #se borra el contenido de la fila
                matrizPago[fila][x] = ""

    vaPagando = Decimal("0.00")
    for fila in xrange(cantidadRenglones):
        if (matrizPago[fila][4] != ""): vaPagando += Decimal(matrizPago[fila][4]).quantize(decimales)
        
    for fil in xrange(cantidadRenglones):
        for col in xrange(5):
            grillaPago.SetCellValue(fil,col,matrizPago[fil][col])    

    retorna = vaPagando, error
    return retorna
    
#*******************************************************************************

def descontarSaldoNC(cantidadNC,idcliente):
    consultaSQL = "SELECT * FROM vtas_ctasctes WHERE idcliente = '%s' AND montocuota <> montopagado AND montocuota < 0 ORDER BY vencimiento" % (idcliente)
    resultado = consultasBD.ordenCrudaDict(consultaSQL)
    if len(resultado) <= 0:
        return
    print "TOTAL NC A DESCONTAR: $",cantidadNC
    resto = cantidadNC
    sentenciasSQL = []
    for registro in resultado:
        if resto == Decimal("0.00"): #se ha descontado todo el credito a favor del cliente y se sale
            break
        diferencia = (registro['montocuota'] - registro['montopagado']).quantize(Decimal('0.10'), rounding=ROUND_UP)
        if abs(diferencia) <= abs(resto):
            resto -= diferencia #queda plata por descontar al cliente
            aDescontar = registro['montopagado'] + diferencia
        else:
            aDescontar = registro['montopagado'] + resto
            resto = Decimal("0.00")
           
        tabla          = "vtas_ctasctes"
        camposyvalores = "montopagado = '%s'" % (aDescontar)
        condicion      = "idventa = '%s' AND nrofactura = '%s' AND cuota = '%s' AND idcliente = '%s'" % (registro['idventa'],registro['nrofactura'],registro['cuota'],registro['idcliente'])
        consultaSQL    = "UPDATE %s SET %s WHERE %s" % (tabla,camposyvalores,condicion)
        utiles.logOperaciones("Pagos.py: descontando NC")
        consultasBD.executaSinCommit(None, consultaSQL)
        sincronizar_tabla.addChange(sql=consultaSQL)         

#*******************************************************************************

def calculoMontosCuotas(cantidadCuotas,montoCuotas,totalRenglon):
    totalMultiplicado = cantidadCuotas * montoCuotas
    diferencia = totalRenglon - totalMultiplicado
    valorCuota = montoCuotas + diferencia
    listaMontos = []
    for i in xrange(cantidadCuotas-1):
        listaMontos.append(montoCuotas)
    listaMontos.append(valorCuota)
    return listaMontos
    
def guardarValoresRecibidos(grillaPago,idventa,nrofactura,sucursal,idcliente,vendedora,totalSaldo):

    #se determina la precision de redondeo con la que se trabajara en Decimal
    #precision = getcontext()
    #precision.prec = 20
    decimales = Decimal('0.10')

    fechaActual = utiles.getfechaInverse()
    nroSucursal = str(utiles.getSucursalActiva())
    nroRecibo = utiles.secuencia("vtas_valores", nroSucursal)
    
    matrizPago = [["","","","",""],["","","","",""],["","","","",""],["","","","",""]]
    #guardo la grilla de pagos para enviar a procesar los valores recibidos
    cantidadRenglones = grillaPago.GetNumberRows()
    for fil in xrange(cantidadRenglones):
        for col in xrange(5):
            matrizPago[fil][col] = grillaPago.GetCellValue(fil,col)
        if matrizPago[fil][0] != "":
            #ingresar una descripcion extendida por el pago realizado
            descripcion = DescripcionPagos.Dialog1(None, matrizPago[fil])
            try:
                descripcion.ShowModal()
            finally:
                descripcion.Destroy()

    detalleCuotas = ["DETALLE DE CUOTAS"]

    for fila in xrange(cantidadRenglones):

        if matrizPago[fila][0] != "":
            #busco informacion sobre la forma de pago. En este punto se supone ya validada toda la informacion
            #en la matriz debido a que previamente fue procesada en Pagos.py mediante Pagos.verificaActualiza()
            tabla     = "valores"
            campos    = "tipo"
            condicion = "nombre = '%s'" % (matrizPago[fila][0])
            consultaSQL = "SELECT %s FROM %s WHERE %s" % (campos,tabla,condicion)
            resultado = consultasBD.ordenCrudaDict(consultaSQL)
            if resultado != None:
                if len(resultado) <= 0:
                    msgerror = "No pudo recuperarse informacion de la base de datos"
                    coderror = -1
                    error = (msgerror,coderror)
                    return error
                else:
                    tipo = resultado[0]['tipo']
            
            if tipo == 0:
                #venta contado, con tarjeta de credito, debito o cheque... o cancelacion con Nota de Credito
                tabla       = "ventastienepagos"
                campos      = "(idventa,nrofactura,fecha,idcliente,idformapagos,descrivalor,monto,cuotas,nrorecibo,vendedora)"
                valores     = "('%s','%s','%s','%s'," % (idventa,str(nrofactura),fechaActual,str(idcliente))
                valores    += "'%s','%s','%s'," % (str(matrizPago[fila][0]),matrizPago[fila][1],matrizPago[fila][4])
                valores    += "'%s','%s','%s')" % (matrizPago[fila][2],str(nroRecibo),vendedora)
                consultaSQL = "INSERT INTO %s%s VALUES %s" % (tabla,campos,valores)
                consultasBD.executaSinCommit(None, consultaSQL)
                sincronizar_tabla.addChange(sql=consultaSQL)
                
                #si el cliente paga con NC, debe reducirse estos importes de vtas_ctasctes
                if str(matrizPago[fila][0]).upper() == "NC":
                    descontarSaldoNC(Decimal(str(matrizPago[fila][4])),str(idcliente))

            else: #el pago viene en cuotas: cuentas corrientes o tarjeta sussan
                
                #determino monto de cada cuota con precision, redondeando decimales
                listaMontos = calculoMontosCuotas(Decimal(matrizPago[fila][2]),Decimal(matrizPago[fila][3]),Decimal(matrizPago[fila][4]))
                if tipo == 1: 
                    #es una condicion de credito y deben calcularse las fechas de vencimiento
                    #cuenta corriente calcula fecha cada 30 dias a partir de la fecha de compra
                    tabla    = "vtas_ctasctes"
                    campos   = "(idventa,nrofactura,vencimiento,idcliente,idformapagos,descripcion,cuota,montocuota,montopagado)"
                    fechaCuota = utiles.strToDate(fechaActual) #transformo string fecha Y-m-d a datetime
                    descripcion = "Cta.Cte. "+matrizPago[fila][2]+" cuotas"
                    detalleCuotas.append(descripcion)

                    for nroCuota,montoCuota in enumerate(listaMontos):
                        fechaCuota = utiles.getFechaLaboralMesSiguiente(fechaCuota)
                        valorescampos = "('"+idventa+"',"+str(nrofactura)+",'"+str(fechaCuota)+"','"+str(idcliente)+"','"+str(matrizPago[fila][0])+"','"+matrizPago[fila][1]+"',"+str(nroCuota+1)+","+str(montoCuota)+",0.0)"
                        consultaSQL = "INSERT INTO "+tabla+campos+" VALUES "+valorescampos
                        consultasBD.executaSinCommit(None, consultaSQL)
                        sincronizar_tabla.addChange(sql=consultaSQL)

                        totalSaldo += Decimal(str(montoCuota))
                        
                        aux = str(fechaCuota)
                        aux = aux[-2:]+"-"+aux[5:7]+"-"+aux[0:4]
                        descripcion = "Venc: "+aux+" $"+str(montoCuota)
                        detalleCuotas.append(descripcion)

                else: 
                    #Tarjeta Sussan: tiene fecha de cierre mensual fija, segun se indique en la tabla parametro
                    #se determina la fecha de cierre y la de proximo vencimiento
                    sentenciaSQL = "select fechacierretarjeta,fechavencimientotarjeta from parametros where sucursal = '%s'" % (str(sucursal))
                    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
                    if resultado == None:
                        msgerror = "No se ha encontrado informacion de parametros"
                        coderror = -1
                        error = (msgerror,coderror)
                        return error
                    diacierre = '%02d' % int(resultado[0]['fechacierretarjeta'])
                    diavencimiento = '%02d' % int(resultado[0]['fechavencimientotarjeta'])
                    mesactual = time.strptime(fechaActual,"%Y-%m-%d")[1] + 1
                    anioactual = time.strptime(fechaActual,"%Y-%m-%d")[0]
                    if mesactual > 12: #cambio de anio
                            mesactual = 1
                            anioactual += 1
                    if (fechaActual[-2:] > diacierre) :
                        #si la compra se hace el dia posterior al cierre, 
                        #el mes de vencimiento es el siguiente al siguiente (ejemplo 1: hoy es 29-02, la compra
                        #vence el 10-04, no el 10-03. ejemplo 2: hoy es 27-02, la compra vence el 10-03)
                        mesactual += 1
                        if mesactual > 12: #cambio de anio
                            mesactual = 1
                            anioactual += 1
                    tablaSQL = "vtas_ctasctes(idventa,nrofactura,vencimiento,idcliente,idformapagos,descripcion,cuota,montocuota,montopagado)"
                    descripcion = "Tarj. Sussan "+matrizPago[fila][2]+" cuotas"
                    detalleCuotas.append(descripcion)

                    for nroCuota,montoCuota in enumerate(listaMontos):
                        fechaVencimiento = str(anioactual)+"-"+('%02d'%mesactual)+"-"+diavencimiento
                        if utiles.isDiaNoLaboral(utiles.strToDate(fechaVencimiento)):
                            fechaVencimiento = str(utiles.getfechaDiaLaboralSiguiente(utiles.strToDate(fechaVencimiento)))
                        camposSQL = "('%s','%s','%s','%s','%s','%s','%s','%s','%s')" % (idventa,str(nrofactura),str(fechaVencimiento),idcliente,str(matrizPago[fila][0]),matrizPago[fila][1],str(nroCuota+1),str(montoCuota),"0.00")
                        #camposSQL = "('"+idventa+"',"+str(nrofactura)+",'"+str(fechaVencimiento)+"','"+idcliente+"','"+str(matrizPago[fila][0])+"','"+matrizPago[fila][1]+"',"+str(nroCuota+1)+","+str(montoCuota)+",0.0)"
                        consultaSQL = "INSERT INTO "+tablaSQL+" VALUES "+camposSQL
                        consultasBD.executaSinCommit(None, consultaSQL)
                        sincronizar_tabla.addChange(sql=consultaSQL)            

                        totalSaldo += Decimal(str(montoCuota))

                        aux = str(fechaVencimiento)
                        aux = aux[-2:]+"-"+aux[5:7]+"-"+aux[0:4]
                        descripcion = "Venc: "+aux+" $"+str(montoCuota)
                        detalleCuotas.append(descripcion)

                        mesactual += 1
                        if mesactual > 12: #cambio de anio
                            mesactual = 1
                            anioactual += 1

                descripcion = "TOTAL SALDO CUENTA: $"+str(totalSaldo)
                detalleCuotas.append(" ")
                detalleCuotas.append(descripcion)

    codigo = 0
    fin = (detalleCuotas,codigo)
    return fin

#*******************************************************************************

def cancelandoSaldoMigracion(datosCliente,grillaPago,valoresEntregados,saldoInicial,idCliente,vendedora):
    
    textoRecibo  = []

    saldoPendiente = saldoInicial - valoresEntregados
    
    sentenciasSQL = []
    
    #generar Recibo para valores informados (entregados por el cliente)
    nroSucursal = str(utiles.getSucursalActiva())
    nroRecibo = utiles.secuencia("vtas_valores", nroSucursal)
    fechaActual = utiles.getfechaInverse()
    nombreCliente = utiles.obtenerNombreCliente(idCliente)+" / cliente nro. "+str(idCliente)

    #cabecera para la impresora fiscal
    nombre = str(datosCliente['nombre'][:30])+" / cliente nro. "+str(idCliente)
    nrodoc = str(datosCliente['nrodoc'])
    respon = str(responsabilidad[datosCliente['situacionfiscal']])
    tipod  = str(tipodoc[datosCliente['tipodoc']])
    domici = str(datosCliente['direccion'])

    #generando cabecera del RECIBO
    textoRecibo.append("RECIBO Nro. "+nroRecibo)
    textoRecibo.append("Fecha: "+utiles.getfecha())
    textoRecibo.append(" ")
    textoRecibo.append("Recibi de "+nombreCliente)
    textoRecibo.append("la suma en pesos:")
    textoRecibo.append(utiles.aLetras(float(valoresEntregados)))
    textoRecibo.append("segun el siguiente detalle:")

    #generando sentencias SQL para almacenar valores
    totFilasPagos = grillaPago.GetNumberRows()
    for fil in xrange(totFilasPagos):
        if grillaPago.GetCellValue(fil, 0) != "":
            idformapago = grillaPago.GetCellValue(fil, 0)
            descripcion = "Pago saldo inicial / "+utiles.getfecha()
            montopago   = grillaPago.GetCellValue(fil, 4)
            tablaycampos = "vtas_valores(idrecibo,idcliente,idformapago,montopago,descripcion,vendedora)"
            valorescampos = "('%s','%s','%s','%s','%s','%s')" % (nroRecibo,idCliente,idformapago,montopago,descripcion,vendedora)

            consultaSQL = "INSERT INTO %s VALUES %s" % (tablaycampos,valorescampos)
            utiles.logOperaciones("Pagos.py: guardando valores recibidos para cancelar saldo migracion")
            consultasBD.executaSinCommit(None, consultaSQL)
            sincronizar_tabla.addChange(sql=consultaSQL)         
           
            descripcion = str(grillaPago.GetCellValue(fil, 1))
            textoRecibo.append("- "+descripcion+" $"+montopago)

    textoRecibo.append(" ")
    textoRecibo.append("Cancelacion del saldo de migracion")
    textoRecibo.append("Total entregado: $"+str(valoresEntregados))
    textoRecibo.append("Saldo pendiente: $"+str(saldoPendiente))
    
    consultaSQL = "UPDATE saldos SET saldoinicial = '%s' WHERE idcliente = '%s'" % (saldoPendiente,idCliente)
    utiles.logOperaciones("Pagos.py: actualizando saldo migracion")
    consultasBD.executaSinCommit(None, consultaSQL)
    sincronizar_tabla.addChange(sql=consultaSQL)         
    
    #actualizarBaseDeDatos(sentenciasSQL)

    #aqui se envian los datos a la impresora fiscal
    DatosCliente = [nombre,nrodoc,respon,tipod,domici]
    utiles.logOperaciones("Enviando datos del cliente a la impresora fiscal")
    utiles.logOperaciones(str(DatosCliente))
    sql = "SELECT hasar_parametroCliente FROM parametros WHERE sucursal = '%s'" % (utiles.getSucursalActiva())
    parametro = consultasBD.ordenCrudaDict(sql)[0]['hasar_parametroCliente']
    
    if not fiscal.enviarCliente(DatosCliente,parametro):
        utiles.mensaje(None,"No pudo configurarse el cliente en la impresora")
    utiles.logOperaciones("Imprimiendo texto del recibo")
    
    
    #ESTE es para la tickeadora
    #Imprimir.imprimirRecibo(textoRecibo,nroRecibo)
    
    #este es para la laser
    Imprimir.imprimirReciboEnImpresoraLaser(textoRecibo,nroRecibo)

    textoRecibido = []
    
#*******************************************************************************

##def actualizarBaseDeDatos(listaConsultas):
##    print "ACTUALIZACION MASIVA DE LA BD"
##    utiles.logOperaciones("Pagos.py: actualizarBaseDeDatos()")
##    for consultaSQL in listaConsultas:
##        consultasBD.executaSinCommit(None, consultaSQL)
##        sincronizar_tabla.addChange(sql=consultaSQL)         

#*******************************************************************************

def imprimirPieRecibo(textoRecibo,nroRecibo,DatosCliente,totalPagado,saldoCtaCte):
        #comienza la comunicacion con la impresora fiscal y se imprime el recibo
        #textoRecibo.append(" ")
        #textoRecibo.append("Total: $"+str(totalPagado.quantize(Decimal('0.10'), rounding=ROUND_UP)))
        textoRecibo.append(" ")
        textoRecibo.append("TOTAL SALDO CTA. CTE: $"+str(saldoCtaCte.quantize(Decimal('0.10'), rounding=ROUND_UP)))

        print "*"*40
        for renglon in textoRecibo:
            print renglon
        print "*"*40

        print "IMPRIMIENDO EL RECIBO"
        
        # LO comentado es para el recibo en el ticket fiscal, lo otro es para la LASER
##        utiles.logOperaciones("Enviando datos del cliente a la impresora fiscal")
##        utiles.logOperaciones(str(DatosCliente))
##        sql = "SELECT hasar_parametroCliente FROM parametros WHERE sucursal = '%s'" % (utiles.getSucursalActiva())
##        parametro = consultasBD.ordenCrudaDict(sql)[0]['hasar_parametroCliente']
##
##        if not fiscal.enviarCliente(DatosCliente,parametro):
##            utiles.mensaje(None,"No pudo configurarse el cliente en la impresora")
##        utiles.logOperaciones("Imprimiendo texto del recibo")
##        Imprimir.imprimirRecibo(textoRecibo,nroRecibo)

        Imprimir.imprimirReciboEnImpresoraLaser(textoRecibo,nroRecibo)



#*******************************************************************************

def guardarValoresRecibidosCtaCte(grillaDeuda,grillaPago,valoresEntregados,totalAPagar,idCliente, datosCliente, \
                                  listaVencido,listaRecargo,listaEnFecha,listaFuturo,vendedora):
    textoRecibo  = []
    #listaPagos -> renglones marcados de la grilla Deuda
    #valoresEntregados -> valores reales informados por el cliente
    #totalAPagar -> el monto que se dice se quiere pagar

    valoresEntregados = Decimal(valoresEntregados)
    totalAPagar = Decimal(totalAPagar)
    totFilasDeuda = grillaDeuda.GetNumberRows()
    totalSaldo = Decimal("0.00")
    if utiles.isDecimal(grillaDeuda.GetCellValue(totFilasDeuda-1,7)): # totales por la ultima grilla
        totalSaldo = Decimal(grillaDeuda.GetCellValue(totFilasDeuda-1,7))
    totalSaldoFinal = totalSaldo

    if valoresEntregados == totalSaldo:
        #el cliente quiere pagar todo lo que esta en la grilla, marcado o no
        listaPagos = [fil for fil in xrange(totFilasDeuda)]
    else:
        #se supone que se quiere pagar lo que esta marcado en la grilla
        #si el cliente entrego mas valores, los mismos se imputaran a favor del cliente o sera vuelto a entregar
        listaPagos = listaVencido+listaRecargo+listaEnFecha+listaFuturo

    #totalMarcado contiene lo que se debe pagar
    totalMarcado = Decimal("0.00")
    for fil in listaPagos:
        #total valor cuota - pago parcial anterior de la cuota
        saldo = Decimal(grillaDeuda.GetCellValue(fil,5)) - Decimal(grillaDeuda.GetCellValue(fil,6))
        totalMarcado += saldo
    
    sentenciasSQL = []
    
    #generar Recibo para valores informados (entregados por el cliente)
    nroSucursal = str(utiles.getSucursalActiva())
    nroRecibo = utiles.secuencia("vtas_valores", nroSucursal)
    fechaActual = utiles.getfechaInverse()
    nombreCliente = utiles.obtenerNombreCliente(idCliente)+" / cliente nro. "+str(datosCliente['idcliente'])

    #cabecera para la impresora fiscal
    nombre = str(datosCliente['nombre'][:30])+" / cliente nro. "+str(datosCliente['idcliente'])
    nrodoc = str(datosCliente['nrodoc'])
    respon = str(responsabilidad[datosCliente['situacionfiscal']])
    tipod  = str(tipodoc[datosCliente['tipodoc']])
    domici = str(datosCliente['direccion'])
    DatosCliente = [nombre,nrodoc,respon,tipod,domici]

    #DATOS DEL RECIBO
    textoRecibo.append("RECIBO Nro. "+nroRecibo)
    textoRecibo.append("Fecha: "+utiles.getfecha())
    textoRecibo.append(" ")
    textoRecibo.append("Recibi de "+nombreCliente)
    textoRecibo.append("la suma en pesos:")
    textoRecibo.append(utiles.aLetras(float(valoresEntregados)))
    textoRecibo.append("segun el siguiente detalle:")

    #guardando valores recibidos en vtas_valores
    totFilasPagos = grillaPago.GetNumberRows()
    totColumPagos = grillaPago.GetNumberCols()
    for fil in xrange(totFilasPagos):
        if grillaPago.GetCellValue(fil, 0) != "":
            idformapago = grillaPago.GetCellValue(fil, 0)
            midescripcion = grillaPago.GetCellValue(fil, 1)
            cuotas = grillaPago.GetCellValue(fil, 2)
            monto = grillaPago.GetCellValue(fil, 3)
            montopago   = grillaPago.GetCellValue(fil, 4)
            lista = [idformapago,midescripcion,cuotas,monto,montopago]
            descripcion = DescripcionPagos.Dialog1(None, lista)
            midescripcion = "-"
            try:
                descripcion.ShowModal()
            finally:
                midescripcion = descripcion.getDescripcion()
                descripcion.Destroy()
            descripcion = midescripcion
            tablaycampos = "vtas_valores(idrecibo,idcliente,idformapago,montopago,descripcion,vendedora)"
            valorescampos = "('%s','%s','%s','%s','%s','%s')" % (nroRecibo,idCliente,idformapago,montopago,descripcion,vendedora)

            consultaSQL = "INSERT INTO %s VALUES %s" % (tablaycampos,valorescampos)
            utiles.logOperaciones("Pagos.py: guardando valores en vtas_valores")
            consultasBD.executaSinCommit(None, consultaSQL)
            sincronizar_tabla.addChange(sql=consultaSQL)         
           
            textoRecibo.append("- "+descripcion+" $"+montopago)

    totalNC = Decimal("0.00")
    for renglon in xrange(totFilasDeuda):
        if str(grillaDeuda.GetCellValue(renglon,2)) == "P":
            totalNC += Decimal(str(grillaDeuda.GetCellValue(renglon,5))) - Decimal(str(grillaDeuda.GetCellValue(renglon,6)))
            #elimino el valor negativo de la grilla informando como ya pagado. Al mismo tiempo lo acumulo en totalNC
            #y se sumara (como positivo) en el total de valoresEntregados. Si al final de todo el procesamiento sigue
            #habiendo plata a favor del cliente, esta se volvera a imputar como credito a su favor, un nuevo registro
            #de cuenta corriente.
            grillaDeuda.SetCellValue(renglon,6,grillaDeuda.GetCellValue(renglon,5))
            miNroFactura = str(grillaDeuda.GetCellValue(renglon,3))
            tabla          = "vtas_ctasctes"
            camposyvalores = "montopagado = '%s', idrecibo = '%s'" % (str(grillaDeuda.GetCellValue(renglon,5)),nroRecibo)
            condicion      = "montocuota = '%s' AND nrofactura = '%s' AND idformapagos = 'P' AND cuota = '0' AND idcliente = '%s'" % (str(grillaDeuda.GetCellValue(renglon,5)),miNroFactura,idCliente)
            consultaSQL = "UPDATE %s SET %s WHERE %s" % (tabla,camposyvalores,condicion)
            utiles.logOperaciones("Pagos.py: procesando N.C.")
            consultasBD.executaSinCommit(None, consultaSQL)
            sincronizar_tabla.addChange(sql=consultaSQL)         

            valorNotaCredito = Decimal("-1.00")*Decimal(str(grillaDeuda.GetCellValue(renglon,5)))
            valorNotaCredito = valorNotaCredito.quantize(Decimal('0.10'), rounding=ROUND_UP)
            textoRecibo.append("- NC/Saldo a favor del cliente $"+str(valorNotaCredito.quantize(Decimal('0.10'), rounding=ROUND_UP)))
    
    #textoRecibo.append(" ")
    #textoRecibo.append("Detalle de cuotas pagadas:")
    #textoRecibo.append(" ")
    #FIN CABECERA RECIBO

    resto = valoresEntregados + (Decimal("-1.00") * totalNC)
    totalPagado = Decimal("0.00")
    
    if (listaPagos != []):
        #se procesan los valores marcados en la grilla en primer lugar, ya que
        #se entiende que se tiene voluntad de pagarlos primero. Pero si el saldo
        #de la grilla coincide con la plata entregada, tambien se interpreta que
        #el cliente tiene la voluntad de pagar todo lo que esta en la grilla,
        #marcado o no.

        #debo tomar la informacion de listaPagos si hay algo marcado
        for fil in listaPagos:
            
            if resto <= Decimal("0.00"):
                #me quede sin plata para asignar a cuotas/recargos
                #Valido para situaciones en la que el total de valoresEntregados
                #es inferior al total de los renglones marcados.
                break

            #calculando el monto a informar como pagado
            montoCuota = grillaDeuda.GetCellValue(fil,5)
            if montoCuota == "": montoCuota = "0.00"
            montoPagado = grillaDeuda.GetCellValue(fil,6)
            if montoPagado == "": montoPagado = "0.00"

            diferencia = Decimal(montoCuota) - Decimal(montoPagado)
            montoImpago = diferencia
            if diferencia == Decimal("0.00"): #ya se pago y no es necesario procesar este renglon
                continue
            if resto >= diferencia:
                #hay plata para pagar
                montoPagado = "0.00"
                aPagar = Decimal(montoCuota)
                resto  = resto - diferencia
                totalPagado += diferencia
            else:
                #no alcanza la plata para pagar
                aPagar = resto
                montoImpago = resto
                resto = Decimal("0.00")
                totalPagado += aPagar

            totalSaldo -= aPagar

            fechaVen = utiles.invertirFecha(grillaDeuda.GetCellValue(fil,0))
            if grillaDeuda.GetCellValue(fil,1)[:3] == "Cta":
                pass
                #se trata de un recargo y se procesa aparte
                #idrecargo = grillaDeuda.GetCellValue(fil,1).split()[-1:][0]
                #recargo = utiles.obtenerRecargo(idrecargo)

                #aqui se guarda el monto acumulado de pagos en la cuota (una cuota puede pagarse de a poco)
                #tabla          = "vtas_recargos"
                #camposyvalores = "montopagado = '%s', idrecibo = '%s'" % (str(aPagar+Decimal(montoPagado)),nroRecibo)
                #condicion      = "idrecargo = '%s'" % (idrecargo)
                #consultaSQL = "UPDATE %s SET %s WHERE %s" % (tabla,camposyvalores,condicion)
                #utiles.logOperaciones("Pagos.py: pagando recargo")
                #consultasBD.executaSinCommit(None, consultaSQL)
                #sincronizar_tabla.addChange(sql=consultaSQL)         
                
                #aqui se guarda el monto realmente pagado en este pago
                #tablaycampos   = "vtas_recargostienepagos(idrecargo,idrecibo,fecha,montopagado)"
                #valorescampos  = "('%s','%s','%s','%s')" % (idrecargo,nroRecibo,fechaActual,str(montoImpago))
                #consultaSQL = "INSERT INTO %s VALUES %s" % (tablaycampos,valorescampos)
                #utiles.logOperaciones("Pagos.py: guardando lo que se paga")
                #consultasBD.executaSinCommit(None, consultaSQL)
                #sincronizar_tabla.addChange(sql=consultaSQL)         

                #textoRecibo.append("- "+recargo['descripcion']+" $"+str(diferencia.quantize(Decimal('0.10'), rounding=ROUND_UP)))
            else:
                nroCuota = grillaDeuda.GetCellValue(fil,1)
                nroFactura = grillaDeuda.GetCellValue(fil,3)
                
                #aqui se guarda el monto acumulado de pagos en la cuota (una cuota puede pagarse de a poco)
                tabla          = "vtas_ctasctes"
                camposyvalores = "montopagado = '%s', idrecibo = '%s'" % (str(aPagar+Decimal(montoPagado)),nroRecibo)
                condicion      = "nrofactura = '%s' AND vencimiento = '%s' AND idcliente = '%s' AND cuota = '%s'" % (nroFactura,fechaVen,idCliente,nroCuota)
                consultaSQL = "UPDATE %s SET %s WHERE %s" % (tabla,camposyvalores,condicion)
                utiles.logOperaciones("Pagos.py: pagando un cuota, guardando lo que se paga de la misma")
                consultasBD.executaSinCommit(None, consultaSQL)
                sincronizar_tabla.addChange(sql=consultaSQL)         

                #debo tener el idventa del registro updateado para grabarlo en vtas_ctasctestienepagos
                consultaSQL = "SELECT idventa FROM vtas_ctasctes WHERE nrofactura = '%s' AND vencimiento = '%s' AND idcliente = '%s' AND cuota = '%s'" % (nroFactura,fechaVen,idCliente,nroCuota)
                resultado = consultasBD.ordenCrudaDict(consultaSQL)
                idventa = resultado[0]['idventa']
                
                #aqui se guarda el monto realmente pagado en este pago
                tablaycampos   = "vtas_ctasctestienepagos(idventa,nrofactura,idrecibo,fecha,montopagado)"
                valorescampos  = "('%s','%s','%s','%s','%s')" % (idventa,nroFactura,nroRecibo,fechaActual,str(montoImpago))
                consultaSQL = "INSERT INTO %s VALUES %s" % (tablaycampos,valorescampos)
                utiles.logOperaciones("Pagos.py: guardando lo que se paga de la cuota")
                consultasBD.executaSinCommit(None, consultaSQL)
                sincronizar_tabla.addChange(sql=consultaSQL)         

                #textoRecibo.append("- F: "+nroFactura+" C: "+nroCuota+" V:"+grillaDeuda.GetCellValue(fil,0)+" $"+str(diferencia.quantize(Decimal('0.10'), rounding=ROUND_UP)))

    if resto <= Decimal("0.00"): #no queda mas plata que repartir... se cierra el recibo y se sale
        #debe enviarse: lista de textoRecibo, numero de recibo, lista de DatosCliente, totalPagado y saldo Cta Cte
        imprimirPieRecibo(textoRecibo,nroRecibo,DatosCliente,totalPagado,(totalSaldoFinal - valoresEntregados))
        return True

    #si se llega aqui, puede ser por dos razones: 
    #1) todavia hay plata para repartir
    #2) listaPagos = [], lo que significa que el cliente no marco nada y hay plata para repatir

    #realizo una nueva lectura de la BD buscando cuotas impagas mas viejas, porque en la grilla pudo
    #haberse hecho una seleccion parcial de los datos. Asi que no utilizo los datos de grillaDeuda

    consultaSQL = "SELECT * FROM vtas_ctasctes WHERE idcliente = '%s' AND montocuota <> montopagado ORDER BY vencimiento" % (idCliente)
    listaImpagos = consultasBD.ordenCrudaDictSinCommit(consultaSQL)

    sentenciasSQL = []
    
    for deuda in listaImpagos:
        if resto <= Decimal("0.00"):
            break #no queda plata

        diferencia = Decimal(str(deuda['montocuota'])) - Decimal(str(deuda['montopagado']))
        montoImpago = diferencia
        if resto >= diferencia:
            #el exceso de valores es mayor al monto adeudado de la cuota
            deuda['montopagado'] = 0.00
            aPagar = Decimal(str(deuda['montocuota']))
            resto  = resto - diferencia
        else:
            #lo que hay que pagar es mayor a lo que se tiene en resto, nos quedamos sin plata
            aPagar = resto
            montoImpago = resto
            resto = Decimal("0.00")
        
        totalSaldo -= aPagar

        nroFactura = str(deuda['nrofactura'])
        nroCuota = str(deuda['cuota'])
        vencimiento = deuda['vencimiento'].strftime("%d-%m-%Y")
      
        tabla          = "vtas_ctasctes"
        camposyvalores = "montopagado = '%s'" %(str(aPagar+Decimal(str(deuda['montopagado']))))
        condicion      = "idventa = '%s' AND nrofactura = '%s' AND vencimiento = '%s'" % (deuda['idventa'],deuda['nrofactura'],deuda['vencimiento'])
        consultaSQL = "UPDATE %s SET %s WHERE %s" % (tabla,camposyvalores,condicion)
        utiles.logOperaciones("Pagos.py: actualizando lo que se va pagando de la cuota")
        consultasBD.executaSinCommit(None, consultaSQL)
        sincronizar_tabla.addChange(sql=consultaSQL)         

        tablaycampos   = "vtas_ctasctestienepagos(idventa,nrofactura,idrecibo,fecha,montopagado)"
        valorescampos  = "('%s','%s','%s','%s','%s')" % (deuda['idventa'],str(deuda['nrofactura']),nroRecibo,fechaActual,str(montoImpago))
        consultaSQL = "INSERT INTO %s VALUES %s" % (tablaycampos,valorescampos)
        utiles.logOperaciones("Pagos.py: se registra lo que se pago de la cuota correspondiente")
        consultasBD.executaSinCommit(None, consultaSQL)
        sincronizar_tabla.addChange(sql=consultaSQL)         

        #textoRecibo.append("- F: "+nroFactura+" C: "+nroCuota+" V:"+vencimiento+" $"+str(aPagar.quantize(Decimal('0.10'), rounding=ROUND_UP)))
        totalPagado += aPagar
        
        #si hay plata, hay que pagar los recargos de la cuota anterior, si es que hay recargos...
        idrecargo = deuda['idrecargo']
        #while idrecargo != None:
            #queda plata en resto?

        #    if resto <= Decimal("0.00"):
        #        break #no queda plata
            
        #    consultaSQL = "SELECT * FROM vtas_recargos WHERE idrecargo = '%s'" % (idrecargo)
        #    recargo = consultasBD.ordenCrudaDictSinCommit(consultaSQL)[0]
        #    if (recargo['monto'] == recargo['montopagado']) or (recargo['idrecibo'] < "0"):
                #ya se pago o se perdono, voy al siguiente
        #        idrecargo = recargo['idrecargo2']
        #        continue

        #    diferencia = Decimal(str(recargo['monto'])) - Decimal(str(recargo['montopagado']))
        #    montoImpago = diferencia
        #    if resto >= diferencia:
                #el exceso de valores es mayor al monto adeudado del recargo
        #        recargo['montopagado'] = 0.00
        #        aPagar = Decimal(str(recargo['monto']))
        #        resto -= diferencia
        #    else:
                #lo que hay que pagar es mayor a lo que se tiene en resto
        #        aPagar = resto
        #        montoImpago = resto
        #        resto = Decimal("0.00")

         #   totalSaldo -= aPagar

            #tabla          = "vtas_recargos"
            #camposyvalores = "montopagado = '%s', idrecibo = '%s'" % (str(aPagar+Decimal(str(recargo['montopagado']))),nroRecibo)
            #condicion      = "idrecargo = '%s'" % (idrecargo)
            #consultaSQL = "UPDATE %s SET %s WHERE %s" % (tabla,camposyvalores,condicion)
            #utiles.logOperaciones("Pagos.py: actualizacion de recargo: monto pagado")
            #consultasBD.executaSinCommit(None, consultaSQL)
            #sincronizar_tabla.addChange(sql=consultaSQL)         

            #tablaycampos   = "vtas_recargostienepagos(idrecargo,idrecibo,fecha,montopagado)"
            #valorescampos  = "('%s','%s','%s','%s')" % (idrecargo,nroRecibo,fechaActual,str(montoImpago))
            #consultaSQL = "INSERT INTO %s VALUES %s" % (tablaycampos,valorescampos)
            #utiles.logOperaciones("Pagos.py: actualizando lo que se pago del recargo (parcial o total)")
            #consultasBD.executaSinCommit(None, consultaSQL)
            #sincronizar_tabla.addChange(sql=consultaSQL)         

            #textoRecibo.append("- "+recargo['descripcion']+" $"+str(aPagar.quantize(Decimal('0.10'), rounding=ROUND_UP)))
            #totalPagado += aPagar

            #idrecargo = recargo['idrecargo2']

        #sali del bucle, porque no tengo mas plata o porque no hay mas recargos
        #si es por no tener mas plata, se controla al principio del bucle
        #si es por no tener mas recargos, hay que pasar al siguiente registro en listaImpagos

    if resto <= Decimal("0.00"): #no queda mas plata que repartir... se cierra el recibo y se sale
        #debe enviarse: lista de textoRecibo, numero de recibo, lista de DatosCliente, totalPagado y saldo Cta Cte
        imprimirPieRecibo(textoRecibo,nroRecibo,DatosCliente,totalPagado,(totalSaldoFinal - valoresEntregados))
        return True
    else:
        import Dialog2
        texto = "ATENCION!!\n\n"
        texto+= "HAY UN VUELTO DE $"+str(resto.quantize(Decimal('0.10'), rounding=ROUND_UP))+"\n"
        texto+= "LO IMPUTA A FAVOR DEL CLIENTE EN SU\nCUENTA CORRIENTE?\n"
        texto+= "\n(Aceptar = si, Cancelar = No)"
        if not utiles.dialog2(None,texto):
            #debe enviarse: lista de textoRecibo, numero de recibo, lista de DatosCliente, totalPagado y saldo Cta Cte
            imprimirPieRecibo(textoRecibo,nroRecibo,DatosCliente,totalPagado,(totalSaldoFinal - valoresEntregados))
            return True
        
        #guardo valores del vuelto en vtas_valores (ya formaba parte de los valores
        #entregados y previamente guardados, por eso se guarda como monto negativo)
        #Es plata a favor del cliente que queda en nuestro sistema
        montopago = (totalSaldoFinal - valoresEntregados).quantize(Decimal('0.10'), rounding=ROUND_UP)
        descripcion = "Vuelto imputado a la cta cte a favor del cliente"
        tablaycampos = "vtas_valores(idrecibo,idcliente,idformapago,montopago,descripcion,vendedora)"
        valorescampos = "('%s','%s','%s','%s','%s','%s')" % (nroRecibo,idCliente,idformapago,montopago,descripcion,vendedora)

        consultaSQL = "INSERT INTO %s VALUES %s" % (tablaycampos,valorescampos)
        utiles.logOperaciones("Pagos.py: vuelto a favor del cliente")
        consultasBD.executaSinCommit(None, consultaSQL)
        sincronizar_tabla.addChange(sql=consultaSQL)         

        #genero una entrada en la cuenta corriente para
        #indicar que queda plata a favor del cliente
        
        tabla       = "vtas_ctasctes"
        campos      = "(idventa,nrofactura,vencimiento,idcliente,idformapagos,descripcion,cuota,montocuota,montopagado,idrecargo)"
        descripcion = "A favor del cliente"
        idventa     = utiles.secuencia("ventas", utiles.getSucursalActiva())
        
        valorescampos = "('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')" % (str(idventa),'0',str(fechaActual),str(idCliente),'P',descripcion,'0',str(montopago),'0.00','-1')

        consultaSQL = "INSERT INTO "+tabla+campos+" VALUES "+valorescampos
        utiles.logOperaciones("Pagos.py: generando vuelto a favor del cliente")
        consultasBD.executaSinCommit(None, consultaSQL)
        sincronizar_tabla.addChange(sql=consultaSQL)         

        #debe enviarse: lista de textoRecibo, numero de recibo, lista de DatosCliente, totalPagado y saldo Cta Cte
        print totalSaldoFinal
        print valoresEntregados
        imprimirPieRecibo(textoRecibo,nroRecibo,DatosCliente,totalPagado,(totalSaldoFinal - valoresEntregados))

        return True

#*******************************************************************************

